﻿using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Lenic.DI.Lifetimes
{
    /// <summary>
    /// 单例生存周期类【在容器生存周期内每个线程有且只会有一个实例对象】
    /// </summary>
    [DebuggerStepThrough]
    public class ThreadLifetime : LifetimeBase
    {
        #region Private Fields

        [ThreadStatic]
        private static IDictionary<LifetimeCachedKey, object> dic = null;

        #endregion Private Fields

        #region Private Methods

        private static object GetCachedInstance(LifetimeCachedKey key)
        {
            if (dic == null)
                dic = new Dictionary<LifetimeCachedKey, object>(new LifetimeCachedKeyEquality());

            object data = null;
            if (dic.TryGetValue(key, out data))
                return data;
            return null;
        }

        private static void SetCachedInstance(LifetimeCachedKey key, object obj)
        {
            dic[key] = obj;
        }

        #endregion Private Methods

        #region LifetimeBase

        protected override object GetValue<T>(string name, Func<Delegate, T> action)
        {
            var key = new LifetimeCachedKey(typeof(T), name);
            object instance = GetCachedInstance(key);
            if (instance == null)
            {
                lock (this)
                {
                    if ((instance = GetCachedInstance(key)) == null)
                    {
                        var item = action(Function);
                        SetCachedInstance(key, item);

                        return item;
                    }
                }
            }
            return instance;
        }

        #endregion LifetimeBase
    }
}